Skip to content

lateral tables - basic select, batch insert#236

Merged
JasonShin merged 14 commits intomainfrom
batch-insert
Nov 30, 2025
Merged

lateral tables - basic select, batch insert#236
JasonShin merged 14 commits intomainfrom
batch-insert

Conversation

@JasonShin
Copy link
Copy Markdown
Owner

@JasonShin JasonShin commented Nov 22, 2025

First step toward to support JSON query type safety

@JasonShin JasonShin changed the title support batch insert support batch insert & handle table valued functions Nov 23, 2025
@JasonShin JasonShin changed the title support batch insert & handle table valued functions lateral tables - basic select, batch insert Nov 23, 2025
@JasonShin JasonShin requested a review from Copilot November 23, 2025 03:30
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for PostgreSQL table-valued functions (specifically jsonb_to_recordset) to enable type-safe JSON query handling. The changes implement inference of TypeScript types from column definitions in table function aliases (e.g., AS t(id INT, name TEXT)), allowing for batch insert operations and basic select queries with type safety.

  • Adds type inference from table-valued function column definitions
  • Switches from generic SQL dialect to database-specific dialects (PostgreSQL/MySQL)
  • Changes placeholder type inference from boolean to any for better flexibility

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/postgres_lateral_tables.rs New test file for validating jsonb_to_recordset select queries with type generation
tests/postgres_batch_insert.rs New test file for batch insert operations using jsonb_to_recordset
src/ts_generator/types/ts_query.rs Adds from_sqlparser_datatype method and table_valued_function_columns storage
src/ts_generator/sql_parser/translate_query.rs Extracts column definitions from table-valued functions during query translation
src/ts_generator/sql_parser/expressions/translate_expr.rs Updates identifier resolution to check table-valued functions before database schema
src/ts_generator/sql_parser/expressions/translate_table_with_joins.rs Extends table name resolution to handle table-valued functions
src/ts_generator/sql_parser/expressions/translate_wildcard_expr.rs Adds error handling for wildcards with table-valued functions
src/ts_generator/generator.rs Switches from GenericDialect to database-specific dialects
src/core/connection.rs Adds get_db_type method to DBConn
tests/demo/* Updates snapshot files reflecting placeholder type change from boolean to any

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

field.is_nullable,
expr_for_logging,
)?
if let Some(field) = table_details.get(&column_name) {
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The nested if-let chain (lines 202-217) should use if-let-else chaining or early returns to reduce nesting depth and improve readability.

Copilot uses AI. Check for mistakes.
field.is_nullable,
expr_for_logging,
)?;
if let Some(field) = table_details.get(&ident) {
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The nested if-let chain (lines 263-292) mirrors the pattern at lines 202-223 with duplicated error messages. Consider extracting this logic into a helper function to reduce duplication.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings November 25, 2025 23:31
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

use test_utils::{run_test, sandbox::TestConfig};

#[rustfmt::skip]
run_test!(should_support_jsonb_to_recordset_batch_insert, TestConfig::new("postgres", true, None, None),
Copy link

Copilot AI Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test name 'should_support_jsonb_to_recordset_batch_insert' is misleading as this test performs a SELECT query, not a batch insert. Consider renaming to 'should_support_jsonb_to_recordset_select' or similar.

Suggested change
run_test!(should_support_jsonb_to_recordset_batch_insert, TestConfig::new("postgres", true, None, None),
run_test!(should_support_jsonb_to_recordset_select, TestConfig::new("postgres", true, None, None),

Copilot uses AI. Check for mistakes.
use test_utils::{run_test, sandbox::TestConfig};

#[rustfmt::skip]
run_test!(should_support_jsonb_to_recordset_batch_insert, TestConfig::new("postgres", true, None, None),
Copy link

Copilot AI Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate test name 'should_support_jsonb_to_recordset_batch_insert' exists in both postgres_batch_insert.rs and postgres_lateral_tables.rs, which will cause a compilation error. Each test must have a unique name.

Suggested change
run_test!(should_support_jsonb_to_recordset_batch_insert, TestConfig::new("postgres", true, None, None),
run_test!(should_support_jsonb_to_recordset_batch_insert_postgres, TestConfig::new("postgres", true, None, None),

Copilot uses AI. Check for mistakes.
)?
} else {
error!(
"Column '{}' not found in table '{}'. This may be a table-valued function or the column may not exist.",
Copy link

Copilot AI Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error message suggests 'may be a table-valued function' but this code path is only reached after checking table-valued function columns. The message should clarify this is an unexpected scenario, e.g., 'Column not found in table or table-valued function columns'.

Suggested change
"Column '{}' not found in table '{}'. This may be a table-valued function or the column may not exist.",
"Column '{}' not found in table '{}' or table-valued function columns.",

Copilot uses AI. Check for mistakes.
)?;
} else {
error!(
"Column '{}' not found in table '{}' for compound identifier '{}.{}'. This may be a table-valued function.",
Copy link

Copilot AI Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to previous comment, this error message suggests 'may be a table-valued function' but is reached after checking table-valued function columns. The message should be updated to reflect this is an unexpected condition.

Suggested change
"Column '{}' not found in table '{}' for compound identifier '{}.{}'. This may be a table-valued function.",
"Column '{}' not found in table '{}' for compound identifier '{}.{}'. This is unexpected: column not found in either table-valued function columns or database schema.",

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings November 30, 2025 00:12
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +45 to +117
for twj in &child_table_with_joins {
match &twj.relation {
TableFactor::Table {
args: Some(table_fn_args),
alias,
..
} => {
// Extract parameters from function arguments
for arg in &table_fn_args.args {
if let FunctionArg::Unnamed(FunctionArgExpr::Expr(expr))
| FunctionArg::Named {
arg: FunctionArgExpr::Expr(expr),
..
} = arg
{
// Process the expression to extract any parameters
translate_expr(expr, &None, full_table_with_joins, None, ts_query, db_conn, false).await?;
}
}

// Extract column definitions from alias if present
// e.g., AS t(id INT, name TEXT)
if let Some(alias) = alias {
let table_name = DisplayTableAlias(alias).to_string();
let mut columns = HashMap::new();

for col_def in &alias.columns {
let col_name = DisplayIndent(&col_def.name).to_string();
if let Some(data_type) = &col_def.data_type {
let ts_type = TsFieldType::from_sqlparser_datatype(data_type);
columns.insert(col_name, ts_type);
}
}

if !columns.is_empty() {
ts_query.table_valued_function_columns.insert(table_name, columns);
}
}
}
TableFactor::Function { args, alias, .. } => {
// Handle LATERAL functions
for arg in args {
if let FunctionArg::Unnamed(FunctionArgExpr::Expr(expr))
| FunctionArg::Named {
arg: FunctionArgExpr::Expr(expr),
..
} = arg
{
translate_expr(expr, &None, full_table_with_joins, None, ts_query, db_conn, false).await?;
}
}

// Extract column definitions from LATERAL function alias if present
if let Some(alias) = alias {
let table_name = DisplayTableAlias(alias).to_string();
let mut columns = HashMap::new();

for col_def in &alias.columns {
let col_name = DisplayIndent(&col_def.name).to_string();
if let Some(data_type) = &col_def.data_type {
let ts_type = TsFieldType::from_sqlparser_datatype(data_type);
columns.insert(col_name, ts_type);
}
}

if !columns.is_empty() {
ts_query.table_valued_function_columns.insert(table_name, columns);
}
}
}
_ => {}
}
}
Copy link

Copilot AI Nov 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for extracting column definitions from aliases (lines 68-81 and 98-112) is duplicated. Consider extracting this into a helper function to reduce code duplication.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings November 30, 2025 00:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/postgres_lateral_tables.rs Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings November 30, 2025 00:58
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/postgres_lateral_tables.rs
Comment thread src/ts_generator/sql_parser/translate_query.rs Outdated
Comment thread src/ts_generator/sql_parser/expressions/translate_expr.rs Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings November 30, 2025 01:04
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/ts_generator/sql_parser/expressions/translate_expr.rs
Comment thread src/ts_generator/sql_parser/expressions/translate_expr.rs
@JasonShin JasonShin merged commit a35b7fe into main Nov 30, 2025
33 checks passed
@JasonShin JasonShin deleted the batch-insert branch November 30, 2025 01:31
@JasonShin JasonShin mentioned this pull request Nov 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants